/**
 *  ajax请求模块, 底层调用axios发送请求
 *   参考新德汇ajax修改，除去socket，修改默认参数编码方式,与缓存机制的实现，添加更新缓存
 *
 */

import qs from "qs";
import { get, save, LOCAL, SESSION } from "src/utils/storage";
import { Toast } from "antd-mobile";
import { isFormData } from "src/utils";

// 内存缓存数据保存处
const Caches = {};

/** config 自定义配置
 *  cache, // boolean/Object, Object: {local, session, key}
 *          local:数据是否保存到localStorage，
 *          session:数据是否保存到SessionStorage
 *          key：缓存的key，默认取url+query
 *  isJson 配置参数是否为 application/json 编码
 *
 *  customError 是否自行处理后台返回fasle的情况
 */

/**
 * 请求前拦截
 */
export function requestSuccessFunc(config) {
    const type = config.method.toLowerCase();
    // config.headers["systemType"] = "APP";
    if (type === "post") {
        if (config.headers["Content-Type"] === "multipart/form-data") {
            if (config.data && !isFormData(config.data)) {
                let data = new FormData();
                for (let o in config.data) {
                    data.append(o, config.data[o]);
                }
                config.data = data;
            }
        } else if (!config.isJson) {
            // 默认使用 application/x-www-form-urlencoded 编码
            config.data = qs.stringify(config.data, { skipNulls: true });
        }
    }
    // 兼容之前写法
    if (type === "get" && config.data && !config.params) {
        config.params = config.data;
    }
    if (!config._ingore) {
        config.headers.common["token"] = sessionStorage.getItem("token");
    }
    if (config.cache) {
        cacheAdapter(config);
    }
    return config;
}

export function requestFailFunc(requestError) {
    // 自定义发送请求失败逻辑
    console.error("请求失败，这是什么情况?", requestError);
    return Promise.reject(requestError);
}

/**
 * 请求结果预处理
 * @param response
 * @returns {Promise<never>}
 */
export function responseSuccessFunc(response) {
    // 200 success 字段可根据后台配置
    const res = response.data;
    if (response.config.responseType === "arraybuffer") {
        return response;
    } else {
        if (res.code === 400 && res.msg.includes("未授权")) {
            Toast.show({
                icon: "fail",
                content: "你的请求已失效，请重新登录",
            });
            setTimeout(() => {
                sessionStorage.clear();
                window.location.href = `${window.location.href.split("#")[0]}#/home`;
            });
            return res;
        }
        if (res && res.success) {
            const cache = response.config.cache;
            if (cache && !cache.cached) {
                cache.cached = true;
                saveCache(
                    cache.key,
                    response,
                    cache.local ? LOCAL : cache.session ? SESSION : null,
                );
            }
            if (res.data === null) {
                res.data = [];
            }
            return res;
        } else if (!response.config.customError) {
            //用户长时间登录token失效，其他地点登录被挤下，登录超时,退出重新登录
            if (res.code === 20001) {
                toLogin();
            }
            if (res.code && res.code !== 200) {
                Toast.show({
                    icon: "fail",
                    content: res.msg,
                });
            }
            return res;
        } else {
            //用户长时间登录token失效，其他地点登录被挤下，登录超时,退出重新登录
            if (res.code === 20001) {
                toLogin();
            }
            return res;
        }
    }
}

export function responseFailFunc(resError) {
    const status = resError.response && resError.response.status;
    // 登录超时
    if (status === 401) {
        toLogin();
        return;
    }
    if (process.env.NODE_ENV === "development") {
        if (resError.config && resError.config.customError) {
            return Promise.reject(resError);
        }
        let msg = "";
        const url = resError.config && resError.config.url;
        if (resError.message.indexOf("timeout") !== -1) {
            msg = "请求超时,时长：" + resError.config.timeout + "毫秒";
        }
        if (resError.message.indexOf("Network Error") !== -1) {
            msg = "未连接到互联网，请检查网络是否畅通";
        }
        if (status >= 500) {
            msg = "后台服务器异常";
        }
        if (status < 500 && status >= 400) {
            msg = "请求异常异常，前检查请求参数或请求地址是否正确";
        }
        if (url !== undefined) {
            Toast.show({
                icon: "fail",
                content: msg,
            });
        }
    }

    console.log(resError);
    return Promise.reject(resError);
}

/**
 * 获取、更新缓存数据
 * @param config
 *
 */
function cacheAdapter(config) {
    if (typeof config.cache !== "object") {
        config.cache = {};
    }
    config.cache = {
        key: createKey(config.url, config.method, config.params, config.data),
        ...config.cache,
    };
    let cacheData;
    let cache = config.cache;
    if (cache.key) {
        const storage = cache.local ? LOCAL : cache.session ? SESSION : null;
        cacheData = cache.update ? removeCache(cache.key, storage) : getCache(cache.key, storage);
    }
    if (cacheData) {
        config.adapter = function () {
            return new Promise(function (resolve) {
                setTimeout(function () {
                    resolve(cacheData);
                }, 500);
            });
        };
    }
}

/**
 * 创建缓存key, 由请求url、类型、参数、发送数据构成的标识符
 * @param {string} url 请求url
 * @param {string} type 请求类型
 * @param {object} params url参数对象
 * @param {object} data 请求数据
 * @return {string}
 */
function createKey(url, type, params, data) {
    return encodeURIComponent([url, type, JSON.stringify(params), JSON.stringify(data)].join(","));
}

/**
 * 获取缓存
 * @param {string} key 缓存key
 * @param {Storage} storage 保存缓存方式，localStorage/sessionStorage/null
 * @return {String|Object|Array}
 */
function getCache(key, storage) {
    return storage ? get(key, storage) : Caches[key];
}

/**
 * 删除缓存, 删除包含url的缓存
 * @param {string} url 缓存key包含的值
 * @param {Storage} storage 保存缓存方式，localStorage/sessionStorage/null
 *
 */
function removeCache(url, storage) {
    if (storage) {
        for (var i = 0, len = storage.length; i < len; i++) {
            const key = storage.key(i);
            key.includes(url) && storage.removeItem(key);
        }
    } else {
        for (let key in Caches) {
            key.includes(url) && delete Caches[key];
        }
    }
    return null;
}

/**
 * 写入缓存
 * @param {string} key 缓存key
 * @param {Object|Array} data 写入数据
 * @param {Storage} storage 保存缓存方式，localStorage/sessionStorage/null
 */
function saveCache(key, data, storage) {
    if (storage) {
        save(key, data, storage);
    } else {
        Caches[key] = data;
    }
}

function toLogin() {
    Toast.show({
        icon: "fail",
        content: "登录超时，请重新登录",
    });
    sessionStorage.clear();
    window.location.href = `${window.location.href.split("#")[0]}#/login`;
    window.location.reload();
}
